<?php

	/**
	 * @see Bike_Initial
	 */
	require_once 'Bike/Initial.php';
	
	
	class Bike_File extends Bike_Initial
	{		const PS = DIRECTORY_SEPARATOR;
		const MODE = 0755;
		
		static protected $_resourceFunctions = array('fclose','feof','fflush','fgetc','fgetcsv','fgets','fgetss',
														'flock','fpassthru','fputcsv','fputs','fread','fscanf','fseek',
														'fstat','ftell','ftruncate','fwrite','rewind');

		protected $_fileName;
		protected $_mode;
		protected $_resource;
		protected $_useDestruct;

		static public function getResourceFunctions()
		{			return self::$_resourceFunctions;
		}

		static public function factory()
		{			$args = func_get_args();
			$File = new self();
			if(sizeof($args))
			{
				$File->setOptions($File->makeOptions($args));
			}
			return $File;
		}

		static public function tmpFile()
		{
			$fileName = sys_get_temp_dir().'/'.strtolower(__CLASS__).time().rand(1,999999);
			$className = __CLASS__.'_Tmp';
			return call_user_func(array($className, 'factory'), $fileName);
		}
		
		static public function ps()
		{
			return self::PS;
		}
		
		static public function mode()
		{
			return self::MODE;
		}

		public function __construct()
		{
			$args = func_get_args();
			parent::__construct($this->makeOptions($args));
		}

		public function init()
		{			$this->useDestruct();
		}

		public function noUseDestruct()
		{			$this->_useDestruct = False;
			return $this;
		}

		public function useDestruct()
		{
			$this->_useDestruct = True;
			return $this;
		}

		public function makeOptions(array $Args=array())
		{			$options = array();
			if(is_array($Args[0]) && array_key_exists('fileName', $Args[0]))
			{				$options = array_shift($Args);
			}
			else
			{
				$options['fileName'] = array_shift($Args);
			}
			return $options;
		}

		public function setFileName($FileName)
		{			$this->_fileName = $FileName;
			return $this;
		}

		public function getFileName()
		{			return $this->_fileName;
		}
		
		public function setMode($mode)
		{
			$this->_mode = $mode;
			return $this;
		}
		
		public function getMode()
		{
			return (is_null($this->_mode)) ? $this->mode() : $this->_mode;
		}

		public function __toString()
		{			return $this->_fileName;
		}

		public function exists()
		{			return $this->file_exists();
		}

		public function rename()
		{
			$args = func_get_args();
			$destFolder = self::factory(dirname(reset($args)));
			if(!$destFolder->is_dir())
			{
				$destFolder->mkdir($destFolder->getMode(), true);
			}
			array_unshift($args, $this->getFileName());
			$this->close();
			$result = call_user_func_array('rename', $args);
			if($result)
			{				$this->setFileName($args[1]);
			}
			return $this;
		}

		public function move()
		{
			$args = func_get_args();
			return call_user_func_array(array($this, 'rename'), $args);
		}

		public function open()
		{			$args = func_get_args();
			$this->_resource = call_user_func_array(array($this, 'fopen'), $args);
			return $this;
		}

		public function close()
		{
			try
			{				$this->fclose();
			}
			catch(Bike_File_Exception $e)
			{			}
			return $this;
		}

		public function delete()
		{			unlink($this->getFileName());
			return $this;
		}

		public function __destruct()
		{			if($this->_useDestruct)
			{
				$this->close();
			}
		}

		public function __call($MethodName, array $Args=array())
		{			if(is_callable($MethodName))
			{				if(in_array($MethodName, $this->getResourceFunctions()))
				{					if(!$this->_resource)
					{						Throw new Bike_File_Exception('Use open method before '.$MethodName);
					}
					array_unshift($Args, $this->_resource);
				}
				else
				{
					array_unshift($Args, $this->getFileName());
				}
				return call_user_func_array($MethodName, $Args);
			}
			return parent::__call($MethodName, $Args);
		}
	}